package com.catmiw.stock2013.domain;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.catmiw.stock2013.util.DateTool;
import com.catmiw.stock2013.util.PropertyManager;
import com.catmiw.stock2013.util.StringUtil;

public class Stock implements Comparable<Stock> {
	private static Pattern PATTERN_CASH = Pattern.compile("派[\\d .]*元");
	private static Pattern PATTERN_TOTALS = Pattern.compile("总股本[\\d .]*万股");
	private static Pattern PATTERN_NUMBER = Pattern.compile("[\\d.]{1,}");
	private static Pattern PATTERN_DATE = Pattern
			.compile("\\d{4}-\\d{2}-\\d{2}");
	private static Pattern PATTERN_MONTH = Pattern.compile("\\d{4}-\\d{2}");
	private static Pattern PATTERN_CASHDATE1 = Pattern
			.compile("红利发放日:\\d{4}-\\d{2}-\\d{2}");
	private static Pattern PATTERN_CASHDATE2 = Pattern
			.compile("[(除权)|(除息)]{1,}日:\\d{4}-\\d{2}-\\d{2}");
	private static String TABCHAR = "┌─┬┐｜├┼┤└┴┘";

	private String code; //6位股票代码
	private String id; //SH/SZ+6位股票代码
	private String name;
	private StockInfo stockinfo;
	private List<CapitalChange> capChanges;//股本变化
	private List<Earnings> earnings;//年度利润数据
	
	public List<Earnings> getEarnings() {
		return earnings;
	}

	public void setEarnings(List<Earnings> earnings) {
		this.earnings = earnings;
	}

	public String getDataFileName(){
		return PropertyManager.getProperty(id.substring(0,2)+"DiaryDir") + "\\"
				+ id.toLowerCase() + ".day";
	}
	
	public void loadMarketDataFromDiaryFile() {
		if (stockinfo == null) {
			stockinfo = new StockInfo();
		}

		String filename=getDataFileName();
		if (!(new File(filename).exists())) {
			stockinfo.setMarketDay(20991231);
			return;
		}

		int count = (int) (new File(filename).length() / 32);

		java.io.RandomAccessFile raf = null;
		DayData dd = null;
		try {
			raf = new RandomAccessFile(filename, "r");
			byte[] b = new byte[32];

			raf.seek(0);
			raf.read(b);
			dd = new DayData(b);
			stockinfo.setMarketDay(dd.getDate());

			raf.seek((count - 1) * 32);
			raf.read(b);
			dd = new DayData(b);
			stockinfo.setLastTradeDay(dd.getDate());
			stockinfo.setPrice(dd.getClose());

		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			try {
				raf.close();
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	private static String getF10Data(String f10, String kind) {
		StringBuffer buf = new StringBuffer();
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f10),"GBK"));
			String s = null;
			boolean begin = false;
			while ((s = reader.readLine()) != null) {
				if (s.indexOf(kind) >= 0) {
					begin = true;
				}
				if (begin) {
					if (s.indexOf("=========================================================================") >= 0) {
						break;
					}
					buf.append(s.trim() + "\n");
				}
			}
			reader.close();
		} catch (FileNotFoundException e) {
			System.err.println(e.getMessage());
		} catch (IOException e) {
			e.printStackTrace();
		}
		return buf.toString();
	}

	private String f10File() {
		String f10 = null;
		if (id.startsWith("SH")) {
			f10 = PropertyManager.getProperty("F10DataSHDir") + code + ".txt";
		} else {
			f10 = PropertyManager.getProperty("F10DataSZDir") + code + ".txt";
		}
		return f10;
	}

	public void loadCaptialChangeData() {
		List<CapitalChange> lcc = new ArrayList<CapitalChange>();
		setCapChanges(lcc);
		String f10 = f10File();
		if (f10 == null)
			return;

		String text = getF10Data(f10, "<!C股本结构>");
		String t1 = "【历次股本变更状况】";
		String t2 = "─────┼────┼────┼────┼───────────────";
		String t3 = "─────┴────┴────┴────┴───────────────";
		int pos1 = text.indexOf(t1);
		if (pos1 >= 0) {
			pos1 = text.indexOf(t2, pos1);
			int pos2 = text.indexOf(t3, pos1);
			String temp = text.substring(pos1 + t2.length() + 1, pos2);
			String[] tt = temp.split("\n");
			CapitalChange cc = null;

			for (String s : tt) {
				if ("".equals(s.trim())) {
					continue;
				}
				if (s.indexOf("│") >= 0) {
					String[] tt2 = s.split("│");
					String stemp = StringUtil.leftTrim(tt2[0].trim());
					Date date1=DateTool.toDate(stemp);
					if (date1==null){
						cc.setReason(cc.getReason() + StringUtil.leftTrim(s.trim()));
						break;
					}
					cc = new CapitalChange();
					cc.setCode(code);
					cc.setDate(date1);
					stemp = StringUtil.leftTrim(tt2[1].trim());
					if (StringUtil.isNumber(stemp))
						cc.setTotal(Double.parseDouble(stemp) / 10000);
					stemp = StringUtil.leftTrim(tt2[2].trim());
					if (StringUtil.isNumber(stemp))
						cc.setCurrenta(Double.parseDouble(stemp) / 10000);
					stemp = StringUtil.leftTrim(tt2[3].trim());
					if (StringUtil.isNumber(stemp))
						cc.setFacta(Double.parseDouble(stemp) / 10000);
					cc.setReason(StringUtil.leftTrim(tt2[4].trim()));
					cc.setCode(code);
					lcc.add(cc);
				} else {
					cc.setReason(cc.getReason() + StringUtil.leftTrim(s.trim()));
				}
			}
		}
		if (lcc.size() == 0
				&& stockinfo.getMarketDay() > 19500101) {
			CapitalChange cc = new CapitalChange();
			cc.setDate(DateTool.toDate(stockinfo.getMarketDay()));
			cc.setTotal(stockinfo.getTotals());
			cc.setReason("上市-添加");
		}

	}

	public static double verifyTotal(List<CapitalChange> listCap, Date date,
			double total) {
		if (listCap == null || listCap.size() == 0)
			return total;
		double dd = listCap.get(listCap.size() - 1).getTotal();
		for (CapitalChange cc : listCap) {
			
			if (date.after(cc.getDate())) {
				dd = cc.getTotal();
				break;
			}
		}
		double temp = Math.abs(total / dd);
		return (temp > 1.2 || temp < 0.833333) ? dd : total;
	}

	public void loadEarningData(List<CapitalChange> listCap) {
		List<Earnings> lcc = new ArrayList<Earnings>();
		this.setEarnings(lcc);
		String f10 = f10File();
		if (f10 == null)
			return;

		String text = getF10Data(f10, "<!G财务分析>");
		String t1 = "┌";
		String t2 = "┘";
		int pos1 = text.indexOf(t1);
		int pos2 = text.indexOf(t2, pos1 >= 0 ? pos1 : 0);
		while (pos1 >= 0 && pos2 >= pos1) {
			String temp = text.substring(pos1, pos2 + 1);
			if (temp.indexOf("主要指标") >= 0 && temp.indexOf("每股收益") >= 0
					&& temp.indexOf("净利润") >= 0) {
				String tt[] = temp.split("\n");
				Earnings ea[] = new Earnings[4];
				for (String s : tt) {
					if (s.indexOf("主要指标") >= 0) {
						String tt2[] = s.split("│");
						for (int i = 2; i < tt2.length; i++) {
							ea[i - 2] = new Earnings();
							String stemp = StringUtil.leftTrim(tt2[i].trim());
							ea[i - 2].setDate(DateTool.toDate(stemp));
						}
					} else if (s.indexOf("每股收益(元)") >= 0) {
						String tt2[] = s.split("│");
						for (int i = 2; i < tt2.length; i++) {
							String stemp = StringUtil.leftTrim(tt2[i].trim());
							if (StringUtil.isNumber(stemp)) {
								ea[i - 2].setEps(Double.parseDouble(stemp));
							}
						}
					} else if (s.indexOf("净资产收益率(%)") >= 0) {
						String tt2[] = s.split("│");
						for (int i = 2; i < tt2.length; i++) {
							String stemp = StringUtil.leftTrim(tt2[i].trim());
							if (StringUtil.isNumber(stemp)) {
								ea[i - 2]
										.setRoe(Double.parseDouble(stemp) / 100);
							}
						}
					} else if (s.indexOf("净利润(万)") >= 0) {
						String tt2[] = s.split("│");
						for (int i = 2; i < tt2.length; i++) {
							String stemp = StringUtil.leftTrim(tt2[i].trim());
							if (StringUtil.isNumber(stemp)) {
								ea[i - 2].setNetProfit((Double
										.parseDouble(stemp) / 10000));
							}
						}
					} else if (s.indexOf("每股净资产(元)") >= 0) {
						String tt2[] = s.split("│");
						for (int i = 2; i < tt2.length; i++) {
							String stemp = StringUtil.leftTrim(tt2[i].trim());
							if (StringUtil.isNumber(stemp)) {
								ea[i - 2].setNaps((Double.parseDouble(stemp)));
							}
						}
					}
				}
				for (Earnings eaa : ea) {
					if (eaa == null)
						continue;
					if (Math.abs(eaa.getEps()) >= 0.01) {
						eaa.setTotal(eaa.getNetProfit() / eaa.getEps());
					}
					eaa.setTotal(verifyTotal(listCap, eaa.getDate(),
							eaa.getTotal()));

					eaa.setNetAsset(eaa.getTotal() * eaa.getNaps());
					eaa.setCode(this.code);
					lcc.add(eaa);
				}
			}
			pos1 = text.indexOf(t1, pos2);
			pos2 = text.indexOf(t2, pos1 >= 0 ? pos1 : 0);
		}

		text = getF10Data(f10, "<!J历年分配>");
		if (text == null || "".equals(text.trim())) {
			text = getF10Data(f10, "<!J历年分红>");
			if (text == null || "".equals(text.trim()))
				return;
		}
		t1 = "───┬────┬────┬───────────────────────";
		t2 = "───┴────┴────┴───────────────────────";
		pos1 = text.indexOf(t1);
		pos2 = text.lastIndexOf(t2);

		if (pos1 >= 0 && pos2 >= 0) {
			text = text.substring(pos1, pos2);

			text = text.replaceAll("───┴────┴────┴───────────────────────\n",
					" ");
			text = text.replaceAll("───┬────┬────┬───────────────────────\n",
					" ");
			text = text.replaceAll("年度  │ 每股收 │ 净资产 │           分红送配方案\n", " ");
			text = text.replaceAll("│ 益\\(元\\) │ 收益率 │\n", " ");
			text = text.replaceAll("───┼────┼────┼───────────────────────\n",
					" ");

			String tt[] = text.split("\n");

			boolean begin = false;
			Earnings ea = null;

			for (String s : tt) {
				s = StringUtil.leftTrim(s.trim());
				if ("".equals(s))
					continue;
				String st = s.length() >= 5 ? s.substring(0, 5) : s;
				if (st.matches("\\d{4}[中年]")) {
					begin = true;
					st = st.replace("中", "-06-30");
					st = st.replace("年", "-12-31");
					ea = new Earnings();
					ea.setDate(DateTool.toDate(st));
					int index = lcc.indexOf(ea);
					//System.out.println(s);
					String[] tt2 = s.split("│");
					if (index >= 0) {
						ea = lcc.get(index);
					} else {
						ea.setCode(this.code);
						lcc.add(ea);
						String stemp = StringUtil.leftTrim(tt2[1].trim());
						if (StringUtil.isNumber(stemp)) {
							ea.setEps(Double.parseDouble(stemp));
						}
						stemp = StringUtil.leftTrim(tt2[2].trim());
						stemp = stemp.replaceAll("%", "");
						if (StringUtil.isNumber(stemp)) {
							ea.setRoe(Double.parseDouble(stemp) / 100);
						}
						
						//System.out.println(tt2[0]+tt2[1]+tt2[2]+tt2[3]);
						if (tt2.length>=4){
							stemp = StringUtil.leftTrim(tt2[3].trim());
						}
						ea.setTotal(verifyTotal(listCap, ea.getDate(), 0));
						ea.setNetProfit(ea.getTotal() * ea.getEps());
						if (Math.abs(ea.getRoe()) > 0.0001) {
							ea.setNaps(ea.getEps() / ea.getRoe());
						}
						ea.setNetAsset(ea.getTotal() * ea.getNaps());
					}
					if (tt2.length >= 4) {
						ea.setAssign(tt2[3]);
					}
				} else if (begin) {
					if (s.startsWith("───")) {
						begin = false;
					} else {
						ea.setAssign(ea.getAssign()
								+ StringUtil.leftTrim(s.replaceAll("│", "")
										.trim()));
					}
				}
			}

		}
		for (Earnings e : lcc) {
			if (e.getAssign() == null)
				continue;
			Matcher matcher = PATTERN_CASH.matcher(e.getAssign());
			Matcher matcher2 = PATTERN_TOTALS.matcher(e.getAssign());

			if (matcher.find() && matcher2.find()) {
				String temp = matcher.group();
				Matcher m3 = PATTERN_NUMBER.matcher(temp);
				m3.find();
				temp = m3.group();
				double c = Double.parseDouble(temp);

				temp = matcher2.group();
				m3 = PATTERN_NUMBER.matcher(temp);
				m3.find();
				double d = Double.parseDouble(m3.group());

				e.setCash(c * d);
			}
		}
	}

	public List<CapitalChange> getCapChanges() {
		return capChanges;
	}
	public void setCapChanges(List<CapitalChange> capChanges) {
		this.capChanges = capChanges;
	}
	public StockInfo getStockinfo() {
		return stockinfo;
	}
	public void setStockinfo(StockInfo stockinfo) {
		this.stockinfo = stockinfo;
	}
	public String getCode() {
		return code;
	}
	public void setCode(String code) {
		this.code = code;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public boolean equals(Object o){
		if (!(o instanceof Stock)){
			return false;
		}
		Stock s=(Stock)o;
		return id.equals(s.id);
	}
	
	public int hashCode(){
		return id.hashCode();
	}
	public int compareTo(Stock arg0) {
		return code.compareTo(arg0.code);
	}
}
